package com.my.blog.website.controller.user;

import com.github.pagehelper.PageInfo;
import com.my.blog.website.constant.RedisConst;
import com.my.blog.website.constant.WebConst;
import com.my.blog.website.controller.BaseController;
import com.my.blog.website.exception.TipException;
import com.my.blog.website.modal.Bo.CommentBo;
import com.my.blog.website.modal.Vo.ContentVo;
import com.my.blog.website.modal.Vo.UserVo;
import com.my.blog.website.service.*;
import com.my.blog.website.utils.MarkdownUtils;
import com.my.blog.website.utils.Tools;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author geng
 * @title: BlogShowController
 * @projectName my-blog
 * @description: TODO
 * @date 2020/1/14 -- 10:58
 */
@Controller
public class BlogShowController extends BaseController {

    @Autowired
    private IContentService contentService;

    @Autowired
    private ICommentService commentService;

    @Autowired
    private IUserService userService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    private static Logger log = LoggerFactory.getLogger(BlogShowController.class);

    /**
     * 文章页
     *
     * @param request 请求
     * @param id      文章主键
     * @return
     */
    @GetMapping(value = {"blog/{id}", "blog/{id}.html"})
    public String getArticle(HttpServletRequest request, @PathVariable String id) {
        ContentVo contents = contentService.getContents(id);
        List<String> tags = Tools.stringTolist(contents.getTags());
        if (null == contents || "draft".equals(contents.getStatus())) {
            return this.render_404();
        }

        //将contents的浏览量设置为mysql + redis
        int hits = contents.getHits();
        String redisKey = "blog" + id;
        int redisHits = 0;
        stringRedisTemplate.opsForValue().increment(redisKey, 1);
        if (stringRedisTemplate.hasKey(redisKey)) {
            String s = stringRedisTemplate.opsForValue().get(redisKey);
            if (s != null || s.length() != 0) {
                redisHits = Integer.valueOf(s);
                hits += redisHits;
            }
        }
        contents.setHits(hits);

        //处理redis中值大于某个阈值，则进行更新操作
        if (redisHits >= RedisConst.REDIS_MAXHIT)
            updateArticleHit(redisKey, contents.getCid(), hits);

        int authorId = contents.getAuthorId();
        UserVo owner = userService.queryUserById(authorId);

        ContentVo blog = getAndConvert(contents);
        request.setAttribute("blog", blog);
        request.setAttribute("tags", tags);
        request.setAttribute("is_post", true);
        request.setAttribute("owner", owner);
        completeArticle(request, contents);
        return this.render("blog");
    }

    /**
     * 文章页
     *
     * @param request 请求
     * @param id      文章主键
     * @return
     */
    @GetMapping(value = {"blog/{id}/preview", "blog/{id}/preview.html"})
    public String preViewArticle(HttpServletRequest request, @PathVariable String id) {
        ContentVo contents = contentService.getContents(id);
        List<String> tags = Tools.stringTolist(contents.getTags());
        if (null == contents || "draft".equals(contents.getStatus())) {
            return this.render_405();
        }

        //将contents的浏览量设置为mysql + redis
        int hits = contents.getHits();
        log.info("blog id 在 mysql 中hits为{}" + hits);
        String redisKey = "blog" + id;
        if (stringRedisTemplate.hasKey(redisKey)) {
            String s = stringRedisTemplate.opsForValue().get(redisKey);
            if (s != null || s.length() != 0) {
                hits += Integer.valueOf(s);
                log.info("blog id 在 redis 中hits为{}" + s);
            }
        }

        contents.setHits(hits);


        int authorId = contents.getAuthorId();
        UserVo owner = userService.queryUserById(authorId);

        ContentVo blog = getAndConvert(contents);
        request.setAttribute("blog", blog);
        request.setAttribute("tags", tags);
        request.setAttribute("is_post", true);
        request.setAttribute("owner", owner);
        completeArticle(request, contents);
        //预览时候不需要增加点击量
        //  updateArticleHit(contents.getCid(), contents.getHits());
        return this.render("blog");
    }


    /**
     * 将md转化为html
     */
    public ContentVo getAndConvert(ContentVo tmp) {
        ContentVo b = new ContentVo();
        BeanUtils.copyProperties(tmp, b);
        String content = b.getContent();
        b.setContent(MarkdownUtils.markdownToHtmlExtensions(content));
        return b;
    }

    /**
     * 抽取公共方法
     *
     * @param request
     * @param contents
     */
    private void completeArticle(HttpServletRequest request, ContentVo contents) {
        if (contents.getAllowComment()) {
            String cp = request.getParameter("cp");
            if (StringUtils.isBlank(cp)) {
                cp = "1";
            }
            request.setAttribute("cp", cp);
            PageInfo<CommentBo> commentsPaginator = commentService.getComments(contents.getCid(), Integer.parseInt(cp), 6);
            request.setAttribute("comments", commentsPaginator);
        }
    }

    /**
     * 更新文章的点击率
     *
     * @param redisKey
     * @param hits
     */
    @Transactional(rollbackFor = TipException.class)
    public void updateArticleHit(String redisKey, Integer cid, int hits) {
        //只需要写数据库，并且把redis的key移除就可以了
        ContentVo temp = new ContentVo();
        temp.setCid(cid);
        temp.setHits(hits);
        contentService.updateContentByCid(temp);
        //移除key或者清零应该都可以
        if (stringRedisTemplate.hasKey(redisKey))
            stringRedisTemplate.delete(redisKey);
    }

}
